#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <math.h>  

#define DEL() printf("\033[D \033[D")
#define LING 1E-6
#define CONT 4  
#define VOLUE 24
#define TRUE 1
#define FALSE 0

int number[CONT];		
char expression[CONT][20] ;				
int count = 0;

/****************************************
* 从键盘输入，并把输入的值存入变量中
* str:  字符串变量
* n:    接收的长度
* show: '1' 显示， 其它不显示
*
*****************************************/
void cyscanf(char *str, int n, char show)
{
    int len = 0;
    char ch;
    struct termios old_term;
    struct termios cur_term;
    tcgetattr(STDIN_FILENO, &old_term);
    memcpy(&cur_term, &old_term, sizeof(cur_term));
    cur_term.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
    cur_term.c_cc[VMIN] = 1;
    cur_term.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &cur_term);

    while (1)
    {
        ch = getchar();
        if (ch == '\n') break;
        // 删除键特殊处理
        if (ch == 8 && len > 0)
        {
            // backspace
            len--;
            if(show) DEL();
            continue;
        }
        // 方向键处理
        if (ch == '\33')
        {
            ch = getchar();
            if (ch == '[')
            {
                ch = getchar();
                switch (ch)
                {
                    case 'A':
                        //printf("\nMOVEUP");
                        break;
                    case 'B':
                        //printf("\nMOVEDOWN");
                        break;
                    case 'C':
                        //printf("\nMOVERIGHT");
                        break;
                    case 'D':
                        //printf("\nMOVELEFT");
                        break;
                }
                continue;
            }
        }
        if (ch > 31 && ch <127 && len < n)
        {
            if(show == '1') printf("%c", ch);
            str[len++] = ch;
        }
        fflush(stdout);
    }
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_term);
    str[len] = '\0';
    printf("\n");
}
 
void Find(int n)
{
	int i = 0, j = 0;
 
	if (n == 1)
	{
		if (number[0] == 24)
		{
			for (i = 0; i < 20; i++) 
			{
				printf("%c", expression[0][i]) ;
			}
			printf("\t\t") ;
			count ++;
			if((count % 2)==0) 				//使输出时每行三个表达式
				printf("\n") ;
		}
	}
	for(i = 0; i < n; i++)				//查找
	{
		for (j = i + 1; j < n; j++)		//与其后面的查找进行计算
		{
			int a, b, k;	
			char expressiona[20], expressionb[20];
				
			a = number[i] ;
			b = number[j] ;
			number[j] = number[n - 1];
 
			strcpy(expressiona, expression[i]) ;
			strcpy(expressionb, expression[j]) ;
			strcpy(expression[j], expression[n - 1]) ;
			
			sprintf(expression[i], "(%s+%s)", expressiona, expressionb) ;
			number[i] = a + b;
			Find(n-1);
		
			k = a - b;
			if(k >= 0) {
				sprintf(expression[i], "(%s-%s)", expressiona, expressionb) ;
				number[i] = a - b;
				Find(n-1);
			}
			
			k = b - a;
			if(k >= 0) {
				sprintf(expression[i], "(%s-%s)", expressionb, expressiona) ;
				number[i] = b - a;
				Find(n-1);
			}
			
			sprintf(expression[i], "(%s*%s)", expressiona, expressionb) ;
			number[i] = a * b;
			Find(n-1);
			
			if (b != 0)
			{
				sprintf(expression[i], "(%s/%s)", expressiona, expressionb) ;
				k = a % b;
				if(k == 0) {
					number[i] = a / b;
					Find(n-1);
				}
			}
			if (a != 0)
			{
				sprintf(expression[i], "(%s/%s)", expressionb, expressiona) ;
				k = b % a;
				if(k == 0) {
					number[i] = b / a;
					Find(n-1);
				}
			}
			number[i] = a;							// 最后一层的Find(2)调用完成后将a重新赋值给number[i]即number[0]
			number[j] = b;							// 最后一层的Find(2)调用完成后将b重新赋值给nubmer[j]即number[1]
			strcpy(expression[i], expressiona) ;
			strcpy(expression[j], expressionb) ;
		}
	}
}

int main(int argc, char *argv[])
{
    char cmd[50];
    int i, j;

    printf("p24> 请输入命令:\n");
    while(1) {
        printf("p24> ");
        cyscanf(cmd,50,'1');
        if('q' == cmd[0] || 'Q' == cmd[0])
            break;

        for(i = 0; i < CONT; i++)
            number[i] = 0;

        i = 0;
        j = 0;
        while(cmd[i] && j < 4) {
            // 通过ascii码判断是数字0-9
            if(cmd[i] >= 48 && cmd[i] <= 57) {
                number[j] = number[j] * 10 + cmd[i] - 48;
            } else {
                j++;
            }
            i++;
        }
        //printf("%d %d %d %d\n",p[0], p[1], p[2], p[3]);
		for (i = 0; i < CONT; i++)
		{
			memset(expression[i], 20, '\0');
			sprintf(expression[i], "%d", number[i]) ;
		}

        Find(CONT);
    }

    return 0;
}
